package com.gee.spring.cloud.aerospace.simulate.core.satellite.telemetry.task;

import com.gee.spring.cloud.aerospace.simulate.core.satellite.telemetry.common.SateTraceContext;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author gee
 * @since 2025/5/15 10:03
 */
@Slf4j
public class TmFrameTask extends AbstractHandler implements TimerTask {

    private SateTraceContext sateTraceContext;

    public TmFrameTask(List<AbstractHandler> delegateTaskList) {
        super(delegateTaskList);
    }

    @Override
    protected boolean doStop(SateTraceContext sateTraceContext, long simulateTime) {
        log.info("TmArcEndTask doStop");
        sateTraceContext.getTmFrameTimer().stop();
        return true;
    }

    @Override
    protected boolean doStart(SateTraceContext sateTraceContext, long simulateTime) {
        log.info("TmArcEndTask doStart");
        this.sateTraceContext = sateTraceContext;
        return true;
    }

    @Override
    protected boolean doResume(SateTraceContext sateTraceContext, long simulateTime) {
        log.info("TmArcEndTask doResume");
        Instant traceBeginTime = sateTraceContext.getTraceBeginTime();
        Instant traceEndTime = sateTraceContext.getTraceEndTime();
        if (simulateTime >= traceBeginTime.toEpochMilli() && simulateTime < traceEndTime.toEpochMilli()) {
            HashedWheelTimer tmFrameTimer = sateTraceContext.getTmFrameTimer();
            Timeout timeout = tmFrameTimer.newTimeout(this, sateTraceContext.getSatelliteContext().getTmSendIntervalMillis(), TimeUnit.MILLISECONDS);
            sateTraceContext.setTmFrameTimeout(timeout);
        }
        return true;
    }

    @Override
    protected boolean doPause(SateTraceContext sateTraceContext, long simulateTime) {
        log.info("TmArcEndTask doPause");
        Optional.ofNullable(sateTraceContext.getTmFrameTimeout()).ifPresent(Timeout::cancel);
        return true;
    }

    @Override
    public void run(Timeout timeout) throws Exception {
        CompletableFuture.runAsync(() -> {
            log.info("tm frame generate and send, deviceCode: {}", sateTraceContext.getDevCode());
        });
        Timeout newTimeout = timeout.timer().newTimeout(this, sateTraceContext.getSatelliteContext().getTmSendIntervalMillis(), TimeUnit.MILLISECONDS);
        sateTraceContext.setTmFrameTimeout(newTimeout);
    }
}
